using System;
using System.Collections.Generic;

namespace pub.MRU
{
    public class MruItem
    {
        public string Value { get; set; }
        public bool Pinned { get; set; }
    }

    public class MruItemList
    {
        public const int DefaultMaxCount = 4;

        public int MaxCount { get; set; }
        public IMruPersister Persister { get; set; }

        public MruItemList()
        {
            MaxCount = DefaultMaxCount;
        }

        public int ItemCount
        {
            get { return LoadItems().Count; }
        }

        public MruItem ItemAt(int index)
        {
            var items = LoadItems();
            if (index < 0 || index > items.Count)
            {
                return null;
            }
            var info = new MruItem();
            info.Value = items[index].TrimStart('*');
            info.Pinned = items[index].StartsWith("*");
            return info;
        }

        public void Clear()
        {
            Persister.Save(new List<string>(), MaxCount);
        }

        public bool Use(string item)
        {
            ValidateItem(item);

            var items = LoadItems();
            var index = FindItem(items, item);
            if (index == 0)
            {
                return false;
            }
            if (index != -1)
            {
                item = items[index];
                items.RemoveAt(index);
            }
            items.Insert(0, item);
            var count = items.Count;
            if (count > MaxCount)
            {
                for (var n = count - 1; n >= 0; --n)
                {
                    if (!items[n].StartsWith("*"))
                    {
                        items.RemoveAt(n);
                        break;
                    }
                }
            }
            Persister.Save(items, MaxCount);
            return true;
        }

        public void Remove(string item)
        {
            ValidateItem(item);

            var items = LoadItems();
            var index = FindItem(items, item);
            if (index != -1)
            {
                items.RemoveAt(index);
                Persister.Save(items, MaxCount);
            }
        }

        public void Pin(string item)
        {
            ValidateItem(item);

            var items = LoadItems();
            var index = FindItem(items, item);
            if (index != -1)
            {
                items[index] = '*' + item;
                Persister.Save(items, MaxCount);
            }
        }

        public void Unpin(string item)
        {
            ValidateItem(item);

            var items = LoadItems();
            var index = FindItem(items, item);
            if (index != -1)
            {
                items[index] = item;
                Persister.Save(items, MaxCount);
            }
        }

        private void ValidateItem(string item)
        {
            if (item.StartsWith("*"))
            {
                throw new ArgumentException("mru item cannot start with '*'");
            }
        }

        private int FindItem(IList<string> items, string item)
        {
            var index = -1;
            var pinnedItem = '*' + item;
            for (var n = 0; n < items.Count; n++)
            {
                var tItem = items[n];
                if (tItem == item || tItem == pinnedItem)
                {
                    index = n;
                    break;
                }
            }
            return index;
        }

        private IList<string> LoadItems()
        {
            return Persister.Load(MaxCount);
        }
    }
}